﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Kinect;
using Microsoft.Xna;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace KinectTD.Input
{

    //We can only use on kinect at a time so static is fine (even if it is slower), it's just easier (for now at least).
    static class Kinect
    {

        private static KinectSensor sensor;

        #region Actions
        private static bool raisedHands;

        public static bool RaisedHands
        {
            get { return raisedHands; }
        }

        private static Texture2D cursor;

        public static Texture2D Cursor
        {
            get { return cursor; }
            set { cursor = value; }
        }



        #endregion

        //Used for scaling
        private const float SkeletonMaxX = 0.60f;
        private const float SkeletonMaxY = 0.40f;

        private static Vector3 position;

        private static Vector3 leftHandPosition;

        public static Vector3 LeftHandPosition
        {
            get { return leftHandPosition; }
            set { leftHandPosition = value; }
        }
        

        public static Vector3 HandPosition
        {
            get
            {
                return position;
            }
        }

        public static Point CursorPosition
        {
            get { return new Point((int)position.X, (int)position.Y); }
        }
        /// <summary>
        /// Sets the sensor up with all of the values we want
        /// Enables the subsystems we're going to use and starts the sensor reading
        /// </summary>
        public static void Init()
        {
            sensor = (from sensorToCheck in KinectSensor.KinectSensors
                      where sensorToCheck.Status == KinectStatus.Connected
                      select sensorToCheck).FirstOrDefault();

            //Parameters used for skeletal tracking (fairly self explanatory what is happening here)
            TransformSmoothParameters parameters = new TransformSmoothParameters();
            parameters.Smoothing = 0.7f;
            parameters.Correction = 0.3f;
            parameters.Prediction = 0.4f;
            parameters.JitterRadius = 1.0f;
            parameters.MaxDeviationRadius = 0.5f;


            //Enable the subsystems we'll be using
            sensor.SkeletonStream.Enable(parameters);
            sensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
            sensor.DepthStream.Enable(DepthImageFormat.Resolution320x240Fps30);

            //Start the sub system
            sensor.Start();
           
            position = Vector3.Zero;
            cursor = Engine.TestTexture;
            sensor.ElevationAngle = sensor.MaxElevationAngle / 2;

        }

        public static void Update()
        {
         
            //Open the frame
            using (SkeletonFrame skeleFrame = sensor.SkeletonStream.OpenNextFrame(0))
            {
                if (skeleFrame == null)
                    return;
                //Grab all the skeleton data and throw it in an array
                Skeleton[] skeleData = new Skeleton[skeleFrame.SkeletonArrayLength];
                skeleFrame.CopySkeletonDataTo(skeleData);

                foreach (Skeleton skele in skeleData)
                {
                    //Only the first skeleton we track is going to do anything - can be expanded at a later date to have more players
                    //But I don't have enough space in my room to test this.
                    if (skele.TrackingState == SkeletonTrackingState.Tracked)
                    {
                        //We need to make sure we can track the right hand (ignoring the left hand completely)
                        //if (skele.Joints[JointType.HandRight].TrackingState == JointTrackingState.Tracked)
                        if (skele.Joints[JointType.HandRight].TrackingState == JointTrackingState.Tracked && skele.Joints[JointType.HandLeft].TrackingState == JointTrackingState.Tracked)
                        {


                            Joint rightHand = skele.Joints[JointType.HandRight];
                            Joint leftHand = skele.Joints[JointType.HandLeft];

                            rightHand = rightHand.ScaleTo(Engine.GameViewport.Bounds.Width, Engine.GameViewport.Bounds.Height, SkeletonMaxX, SkeletonMaxY);
                            leftHand = leftHand.ScaleTo(Engine.GameViewport.Bounds.Width, Engine.GameViewport.Bounds.Height, SkeletonMaxX, SkeletonMaxY);

                            position.X = rightHand.Position.X;
                            position.Y = rightHand.Position.Y;
                            position.Z = rightHand.Position.Z;

                            leftHandPosition.X = leftHand.Position.X;
                            leftHandPosition.Y = leftHand.Position.Y;
                            leftHandPosition.Z = leftHand.Position.Z;


                            if (skele.Joints[JointType.Head].TrackingState == JointTrackingState.Tracked)
                            {
                             
                                Joint headJoint = skele.Joints[JointType.Head];

                                leftHand = leftHand.ScaleTo(Engine.GameViewport.Bounds.Width, Engine.GameViewport.Bounds.Height, SkeletonMaxX, SkeletonMaxY);
                                headJoint = headJoint.ScaleTo(Engine.GameViewport.Bounds.Width, Engine.GameViewport.Bounds.Height, SkeletonMaxX, SkeletonMaxY);
                                //if (rightHand.Position.Y > headJoint.Position.Y && leftHand.Position.Y > headJoint.Position.Y)
                                //    raisedHands = false;
                                //else
                                //    raisedHands = true;
                            }
                            else
                            {
                                raisedHands = false;
                            }

                            return;
                        }
                    }
                }
            }

        }

        public static void Draw(SpriteBatch sb)
        {
            sb.Begin();
            sb.Draw(cursor, new Rectangle((int)position.X, (int)position.Y, cursor.Width, cursor.Height), Color.White);
            sb.End();
        }

        public static void Unload()
        {
            //Stop the sensor when we're done with it
            sensor.Stop();
        }

    }
}
